/*
 * Copyright [2021-present] [ahoo wang <ahoowang@qq.com> (https://github.com/Ahoo-Wang)].
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *      http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package me.ahoo.wow.saga.stateless

import me.ahoo.wow.command.CommandGateway
import me.ahoo.wow.command.factory.CommandMessageFactory
import me.ahoo.wow.event.AbstractEventFunctionRegistrar
import me.ahoo.wow.event.DomainEventExchange
import me.ahoo.wow.messaging.function.MessageFunction
import me.ahoo.wow.messaging.function.MessageFunctionRegistrar
import me.ahoo.wow.messaging.function.SimpleMessageFunctionRegistrar
import me.ahoo.wow.saga.annotation.statelessSagaMetadata
import reactor.core.publisher.Mono

/**
 * Registrar for stateless saga functions that creates [StatelessSagaFunction] instances
 * from processors annotated with saga metadata.
 *
 * @property commandGateway The gateway used to send commands generated by saga functions.
 * @property commandMessageFactory The factory for creating command messages.
 * @property actual The underlying message function registrar (default: [SimpleMessageFunctionRegistrar]).
 */
class StatelessSagaFunctionRegistrar(
    private val commandGateway: CommandGateway,
    private val commandMessageFactory: CommandMessageFactory,
    actual: MessageFunctionRegistrar<MessageFunction<Any, DomainEventExchange<*>, Mono<*>>> =
        SimpleMessageFunctionRegistrar()
) : AbstractEventFunctionRegistrar(actual) {
    /**
     * Resolves the processor by extracting saga metadata and creating stateless saga functions.
     * This method parses the processor's class for saga annotations and wraps the resulting
     * message functions with [StatelessSagaFunction] to handle command execution.
     *
     * @param processor The processor instance to resolve functions for.
     * @return A set of stateless saga functions for the processor.
     */
    override fun resolveProcessor(processor: Any): Set<MessageFunction<Any, DomainEventExchange<*>, Mono<*>>> =
        processor.javaClass
            .statelessSagaMetadata()
            .toMessageFunctionRegistry(processor)
            .map {
                StatelessSagaFunction(it, commandGateway, commandMessageFactory)
            }.toSet()
}
